﻿<template>
    <el-table :data="page.records" border highlight-current-row size="default" class="cgrid" ref="grid"
        @selection-change="handleSelectionChange" v-bind="$attrs" @cell-click="onRowDbClick" :summary-method="getSummaries"
        :show-summary="sumFields">
        <el-table-column v-if="multi" type="selection" width="50" align="center"></el-table-column>
        <template v-for="col in cols" :key="col.code">
            <el-table-column v-if="col.children" :label="col.label" header-align="center">
                <template v-for="c1 in col.children" :key="c1">
                    <el-table-column :prop="c1.code" :label="c1.label" :formatter="formatCol" header-align="center"
                        :show-overflow-tooltip="getOverflowTooltip(c1)" :width="getWidth(c1)" :align="getAlign(c1)">
                        <template #default="scope" v-if="!disabled && c1.tpl">
                            <component :is="col.tpl.control" v-model="scope.row[c1.code]" v-bind="c1.tpl['props']"
                                :formData="scope.row" />
                        </template>
                    </el-table-column>
                </template>
            </el-table-column>
            <el-table-column v-else-if="col.control == 'photo' || col.control == 'HandWriteBoard' || col.control == 'sign'"
                :prop="col.code" :label="col.label" :width="getWidth(col)" align="center" header-align="center">
                <template #default="scope">
                    <el-image v-for="(item, ix) in getPhotos(scope.row, col.code, col)" :key="item" fit="contain"
                        :src="item" :preview-src-list="getPhotos(scope.row, col.code, col, true)" :initial-index="ix"
                        :style="{ width: getPhotoWidth(col) + 'px', height: getPhotoHeight(col) + 'px' }"></el-image>
                </template>
            </el-table-column>
            <el-table-column v-else-if="col.control == 'check' || col.type == 'bool'  || col.type == 'boolean'" :prop="col.code" :label="col.label"
                :width="getWidth(col)" align="center" header-align="center">
                <template #default="scope">
                    <el-icon v-if="scope.row[col.code]">
                        <Check />
                    </el-icon>
                    <span v-else></span>
                </template>
            </el-table-column>
            <el-table-column v-else-if="col.control == 'action'" :label="col.label" :width="getWidth(col)" align="center">
                <template #default="scope">
                    <el-button v-for="ac in col.actions" :key="ac" type="text" text
                        @click="doColAction(ac.click, scope.row)">{{ getActioLabel(ac, scope.row) }}</el-button>
                </template>
            </el-table-column>
            <el-table-column v-else :prop="col.code" :label="col.label" :formatter="formatCol" header-align="center"
                :show-overflow-tooltip="getOverflowTooltip(col)" :width="getWidth(col)" :align="getAlign(col)">
                <template #default="scope" v-if="!disabled && col.tpl">
                    <component :is="col.tpl.control" v-model="scope.row[col.code]" v-bind="col.tpl['props']"
                        :formData="scope.row" style="width:100%;" />
                </template>
            </el-table-column>
        </template>
    </el-table>
    <el-pagination :layout="$mbh5
            ? 'prev, pager, next'
            : 'total, sizes,prev, pager, next,jumper'
        " background :page-sizes="pageSizes" v-model:current-page="page.pageIndex" v-model:page-size="page.pageSize"
        :total="page.totalCount" hide-on-single-page></el-pagination>

    <my-select-win v-if="selectCfg" ref="selectWin" :title="selectCfg.title" :tbname="selectCfg.tbname"
        :fields="selectCfg.fields" :search="selectCfg.search" @selected="onSelected"></my-select-win>
    <div v-if="selectCfg && !disabled" style="margin-top: 10px">
        <el-button type="danger" :disabled="multipleSelection.length == 0" @click="handleDel">删除</el-button>
        <el-button type="default" @click="handleAdd">添加</el-button>
    </div>
    <div v-if="actions && !disabled" style="margin-top: 10px">
        <el-button v-for="btn in actions" :key="btn" :type="btn.type" @click="doClick(btn.click)">{{ btn.label }}
        </el-button>
    </div>
    <my-form-dlg ref="dlgForm" v-if="editCfg" :tbname="editCfg.tbname" :formName="editCfg.formName" @added="onAdded"
        @updated="onUpdated" @deleted="onDelete" />
</template>

<script>
import { inject } from "vue";
import mydt from "./mydate";
import Utils from "./Utils";
import store from "./store";
import { Check } from '@element-plus/icons-vue'
export default {
    name: "MyChildGrid",
    emits: ["update:modelValue", "afterLoadCfg", "added", "removed", "selected"],
    components: { Check },
    setup() {
        let MyPage = inject("MyPage", {});
        return {
            MyPage,
        };
    },

    props: {
        cols: {
            type: Array,
            required: true,
        },
        multi: Boolean,
        modelValue: Array,
        disabled: Boolean,
        selectCfg: Object,
        formData: Object,
        actions: Array,
        editCfg: Object,
        sumFields: String,
        sortFunc: Function
    },
    data() {
        return {
            pageSizes: [10, 20, 50, 100, 200],
            multipleSelection: [],
            page: {
                pageIndex: 1,
                pageSize: 10,
                pageCount: 0,
                totalCount: 0,
                records: null,
                sumRow: [],
            },
        };
    },
    mounted() {
        if (!this.page.records) {
            this.loadData(1);
        }
    },
    methods: {
        getSummaries(param) {
            try {
                const { columns, data } = param;
                const sums = [];
                const me = this;
                columns.forEach((column, index) => {
                    if (index === 0) {
                        sums[index] = '合计'
                        return
                    }
                    const key = column.property;
                    if (me.sumFields.indexOf(key + ";") > -1) {
                        sums[index] = (this.modelValue && this.modelValue.length > 0) ? 
                            this.modelValue.map(p => p[key]).reduce((total, num) => total + num) 
                            : 0;
                    } else {
                        sums[index] = '';
                    }
                });
                return sums;
            } catch (e) {
                console.log(e);
            }
        },
        getPhoto(photo, max) {
            let list = (photo || "").split(";").filter((p) => p != "");
            if (list.length < 1) {
                return "";
            }
            if (!max || max <= 1) {
                return list[0];
            }
            return list;
        },
        loadData(pageIndex) {
            if (this.formData) {
                this.$emit("afterLoadCfg", this);
                this.$nextTick(function () {
                    this.innerLoadData(pageIndex);
                });
            } else {
                this.innerLoadData(pageIndex);
            }
        },
        innerLoadData(pageIndex) {
            const items = this.modelValue || [];
            if (this.sortFunc) {
                items.sort(this.sortFunc);
            }
            this.page.pageCount = Math.ceil(items.length / this.page.pageSize);
            this.page.totalCount = items.length;
            pageIndex = pageIndex || this.page.pageIndex;
            if (pageIndex > this.page.pageCount) {
                pageIndex = this.page.pageCount;
            }
            if (pageIndex < 1) {
                pageIndex = 1;
            }
            this.page.pageIndex = pageIndex;
            const ix = (pageIndex - 1) * this.page.pageSize;
            const iy = ix + this.page.pageSize;
            this.page.records = items.slice(ix, iy);
        },
        doColAction(fun, row) {
            fun.apply(this, [row, this, this.MyPage]);
        },
        getActioLabel(ac, row) {
            try {
                if (typeof ac.label == "string") {
                    return ac.label;
                } else if (typeof ac.label == "function") {
                    return ac.label.apply(this, [row]);
                }
            } catch { }
            return "无名";
        },
        getComboLabel(value, options) {
            var item = options.filter((p) => p.value == value);
            if (item.length == 1) {
                return item[0].label;
            }
            return value;
        },
        formatCol(row, column, cellValue, index) {
            if (cellValue == undefined) return "";
            if (!column.col) {
                column.col = this.cols.filter(
                    (p) => p.code == column.property
                )[0];
            }
            var col = column.col;

            if (col.control == "combo") {
                let label = this.getComboLabel(cellValue, col.options);
                return label;
            }
            if (col.format != "") {
                switch (col.type) {
                    case "date":
                        return mydt.formatDate(cellValue, col.format);
                }
            }
            return cellValue;
        },
        getOverflowTooltip(col) {
            return (
                col.control == "text" ||
                col.control == "textarea" ||
                col.control == "addr"
            );
        },
        getWidth(col) {
            if (col.width >= 0) {
                return col.width;
            }
            return null;
        },
        getAlign(col) {
            switch (col.control) {
                case "combo":
                    return "center";
            }
            switch (col.type) {
                case "int":
                case "number":
                    return "right";
                case "boolean":
                    return "center";
            }
            return "left";
        },
        handleSelectionChange(val) {
            this.multipleSelection = val;
        },
        getSelected() {
            return this.multipleSelection;
        },
        onRowDbClick(row, column, event) {
            var nowTime = new Date().getTime();
            if (this.lastClickTime && (nowTime - this.lastClickTime) < 300) {
                /*双击*/
                this.lastClickTime = 0;
                this.doEditItem(row);
            } else {
                this.lastClickTime = nowTime;
            }
        },
        doEditItem(row) {
            if (this.editCfg) {
                if (this.editCfg.localEdit) {
                    this.$refs.dlgForm.open(row);
                } else {
                    this.$refs.dlgForm.open(row.ID);
                }
                return;
            }
            this.$emit("selected", row, this, this.MyPage);
        },

        handleDel() {
            if (this.editCfg && !this.editCfg.localEdit) {
                this.multipleSelection.forEach(p => {
                    this.$server.delete(this.editCfg.tbname, p.ID).then(res => {
                        this.$emit("removed", p, this, this.MyPage);
                        let items = this.modelValue.filter(p1 => p1.ID != p.ID);
                        this.$emit("update:modelValue", items);
                    });
                })
                return;
            }
            var items = this.modelValue.filter(
                (p) => this.multipleSelection.indexOf(p) != -1
            );
            this.$emit("removed", items, this, this.MyPage);

            var arr = this.modelValue.filter(
                (p) => this.multipleSelection.indexOf(p) == -1
            );
            this.$emit("update:modelValue", arr);
        },
        handleAdd() {
            if (this.editCfg) {
                var item = { ID: 0 };
                item[this.editCfg.pid] = this.formData.ID;
                if (this.editCfg.localEdit) {
                    this.$refs.dlgForm.open(item);
                } else {
                    this.$refs.dlgForm.open(0, item);
                }
                return;
            }
            if (this.selectCfg) {
                if (this.selectCfg.click) {
                    //如果有自定义click，调用自定义click
                    this.selectCfg.click.apply(this);
                    return;
                }
                if (this.selectCfg.tbname) {
                    if (this.selectCfg.psearch && this.formData) {
                        //取当前formData上的值，做查询条件
                        let ss = { ...this.selectCfg.search };
                        let change = false;
                        Object.keys(this.selectCfg.psearch).forEach((k) => {
                            const v = this.selectCfg.psearch[k];
                            if (v && typeof v == "string") {
                                ss[k] = this.formData[v];
                                if (ss[k] != this.selectCfg.search[k]) {
                                    change = true;
                                }
                            }
                        });
                        if (change) {
                            this.selectCfg.search = ss;
                        }
                    }
                    this.$refs.selectWin.open(true);
                } else {
                    let data = [];
                    if (this.modelValue) {
                        data = this.modelValue.map((p) => p);
                    }

                    let item = {};
                    this.cols.forEach(p => {
                        item[p.code] = p.default || ""
                    })
                    data.push(item);
                    this.$emit("update:modelValue", data);
                }
                return;
            }

            

        },
        onSelected(items) {
            var src = this.selectCfg.srcFields.split(",");
            var dst = this.selectCfg.destFields.split(",");
            let data = [];
            if (this.modelValue) {
                data = this.modelValue.map((p) => p);
            }

            items.forEach((p) => {
                var oldItem = data.filter((p1) => p1[dst[0]] == p[src[0]])[0];
                if (oldItem == undefined) {
                    let newItem = {};
                    for (let ix = 0; ix < src.length; ix++) {
                        newItem[dst[ix]] = p[src[ix]];
                    }
                    data.push(newItem);
                    this.$emit("added", newItem, this, this.MyPage);
                }
            });

            this.$emit("update:modelValue", data);
        },
        getPhotos(row, code, col, getAll) {
            let list = (row[code] || "").split(";").filter((p) => p != "");

            let max = 1;
            let prop = col["photo"];
            if (prop && prop.grid_col && typeof prop.grid_col == "number") {
                max = prop.grid_col;
            }
            if (!getAll) {
                if (list.length > max) {
                    list.splice(max);
                }
            }
            let nitems = list.map(store.getUrl)
            return nitems;
        },
        getPhotoShape(col) {
            let prop = col["photo"];
            if (prop && prop.shape) {
                return prop.shape;
            }
            return "circle";
        },
        getPhotoWidth(col) {
            let prop = col["photo"];
            if (prop) {
                return prop.width || prop.size || 32;
            }
            return 32;
        },
        getPhotoHeight(col) {
            let prop = col["photo"];
            if (prop && prop.size) {
                return prop.height || prop.size || 32;
            }
            return 32;
        },
        doClick(func) {
            Utils.doFunc(func, this);
        },
        onUpdated(item) {
            let newItems = this.modelValue.map(p => {
                if (p.ID == item.ID) {
                    return { ...item };
                }
                return p;
            })
            this.$emit("update:modelValue", newItems);
            if (this.$refs.dlgForm) {
                this.$refs.dlgForm.close()
            }
        },

        onAdded(item) {
            let data = this.modelValue ? this.modelValue.map(p => p) : [];
            data.push({ ...item });
            this.$emit("update:modelValue", data);
            if (this.$refs.dlgForm) {
                this.$refs.dlgForm.close()
            }
        },
        onDelete(item) {
            let data = this.modelValue ? this.modelValue.map(p => p) : [];
            let ix = data.indexOf(item);
            data.splice(ix, 1);
            this.$emit("update:modelValue", data);
            if (this.$refs.dlgForm) {
                this.$refs.dlgForm.close()
            }
        }
    },

    watch: {
        modelValue(newValue) {
            this.loadData(1);
        },
        "page.pageIndex": function () {
            this.loadData();
        },
        "page.pageSize": function () {
            this.loadData(1);
        }
    },
};
</script>

<style scoped>
.cgrid :deep(.el-table__cell) {
    padding: 2px !important;
}
</style>